﻿using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;

namespace JY.Wpf.Core.Tools
{
    /// <summary>
    /// 视图帮助类
    /// </summary>
    public static class VisualHelper
    {
        #region # 查找元素的子元素——T FindVisualChild<T>(DependencyObject reference) where T : DependencyObject
        /// <summary>
        /// 查找元素的子元素
        /// </summary>
        /// <typeparam name="T">子元素类型</typeparam>
        /// <param name="reference">可见对象</param>
        /// <returns></returns>
        public static T FindVisualChild<T>(DependencyObject reference) where T : DependencyObject
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(reference); i++)
            {
                var child = VisualTreeHelper.GetChild(reference, i);
                if (child is T dependencyObject)
                {
                    return dependencyObject;
                }
                else
                {
                    var childOfChild = FindVisualChild<T>(child);
                    if (childOfChild != null)
                    {
                        return childOfChild;
                    }
                }
            }
            return null;
        }
        #endregion

        #region # 获取可见对象指定类型元素的子元素集合——IEnumerable<T> FindVisualChildren<T>(DependencyObject reference) where T : DependencyObject
        /// <summary>
        /// 获取可见对象指定类型元素的子元素集合
        /// </summary>
        /// <typeparam name="T">子元素类型</typeparam>
        /// <param name="reference">可见对象</param>
        /// <returns></returns>
        public static IEnumerable<T> FindVisualChildren<T>(DependencyObject reference) where T : DependencyObject
        {
            if (reference == null) yield break;

            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(reference); i++)
            {
                var child = VisualTreeHelper.GetChild(reference, i);
                if (child is T dependencyObject)
                {
                    yield return dependencyObject;
                }

                foreach (T childOfChild in FindVisualChildren<T>(child))
                {
                    yield return childOfChild;
                }
            }
        }
        #endregion

        #region # 获取可见对象指定类型元素的子元素集合——IEnumerable<T> FindVisualChildren<T>(DependencyObject reference) where T : DependencyObject
        /// <summary>
        /// 获取可见对象指定类型元素的子元素集合
        /// </summary>
        /// <typeparam name="T">子元素类型</typeparam>
        /// <param name="reference">可见对象</param>
        /// <param name="elementName">元素名称</param>
        /// <returns></returns>
        public static IEnumerable<T> FindVisualChildren<T>(DependencyObject reference, string elementName) where T : DependencyObject
        {
            if (reference == null) yield break;

            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(reference); i++)
            {
                var child = VisualTreeHelper.GetChild(reference, i);
                if (child is T dependencyObject &&
                    ((System.Windows.FrameworkElement)child).Name.Equals(elementName))
                {
                    yield return dependencyObject;
                }

                foreach (T childOfChild in FindVisualChildren<T>(child))
                {
                    yield return childOfChild;
                }
            }
        }
        #endregion

        #region # 查找元素的父元素——T FindParent<T>(DependencyObject reference) where T : DependencyObject
        /// <summary>
        /// 查找元素的父元素
        /// </summary>
        /// <typeparam name="T">父元素类型</typeparam>
        /// <param name="reference">可见对象</param>
        /// <returns></returns>
        public static T FindParent<T>(DependencyObject reference) where T : DependencyObject
        {
            var parentDependencyObject = VisualTreeHelper.GetParent(reference);
            if (parentDependencyObject != null)
            {
                if (parentDependencyObject is T dependencyObject)
                {
                    return dependencyObject;
                }
                else
                {
                    parentDependencyObject = FindParent<T>(parentDependencyObject);
                    if (parentDependencyObject != null)
                    {
                        return (T)parentDependencyObject;
                    }
                }
            }
            return null;
        }
        #endregion

        #region # 查找元素的父元素——T FindParent<T>(DependencyObject reference, string elementName) where T : DependencyObject
        /// <summary>
        /// 查找元素的父元素
        /// </summary>
        /// <typeparam name="T">父元素类型</typeparam>
        /// <param name="reference">可见对象</param>
        /// <param name="elementName">元素名称</param>
        /// <returns></returns>
        public static T FindParent<T>(DependencyObject reference, string elementName) where T : DependencyObject
        {
            var parentDependencyObject = VisualTreeHelper.GetParent(reference);
            if (parentDependencyObject != null)
            {
                if (parentDependencyObject is T dependencyObject && 
                    ((System.Windows.FrameworkElement)parentDependencyObject).Name.Equals(elementName))
                {
                    return dependencyObject;
                }
                else
                {
                    parentDependencyObject = FindParent<T>(parentDependencyObject);
                    if (parentDependencyObject != null)
                    {
                        return (T)parentDependencyObject;
                    }
                }
            }
            return null;
        }
        #endregion

        #region # 根据可见对象查找视觉树是否存在指定类型的元素——bool HitTest<T>(DependencyObject reference) where T : DependencyObject
        /// <summary>
        /// 根据可见对象查找视觉树是否存在指定类型的元素
        /// </summary>
        /// <typeparam name="T">元素类型</typeparam>
        /// <param name="reference">可见对象</param>
        public static bool HitTest<T>(DependencyObject reference) where T : DependencyObject
        {
            return FindParent<T>(reference) != null || FindVisualChild<T>(reference) != null;
        }
        #endregion

        #region # 获取可见对象指定类型的第一个元素——T GetChild<T>(DependencyObject reference) where T : DependencyObject
        /// <summary>
        /// 获取可见对象指定类型的第一个元素
        /// </summary>
        /// <typeparam name="T">元素类型</typeparam>
        /// <param name="reference">可见对象</param>
        /// <returns></returns>
        public static T GetChild<T>(DependencyObject reference) where T : DependencyObject
        {
            if (reference is T t)
            {
                return t;
            }

            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(reference); i++)
            {
                var child = VisualTreeHelper.GetChild(reference, i);

                var result = GetChild<T>(child);
                if (result != null) return result;
            }

            return default(T);
        }
        #endregion
        #region # 获取当前应用中处于激活的一个窗口——Window GetActiveWindow()
        /// <summary>
        ///获取当前应用中处于激活的一个窗口
        /// </summary>
        /// <returns></returns>
        public static Window GetActiveWindow() => Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive); 
        #endregion
    }
}
